deferred class CD_LINES

inherit
	CANVAS_DRAW

feature {ANY}

	-- Operations

	draws_line (x1, y1, x2, y2: INTEGER)
		-- Draws a line from (x1,y1) to (x2,y2) using the current foreground
		-- color and line width and style. Both points are included in the line. 
		do
			int_canvas_line (cnvs, x1, y1, x2, y2)
		end

	draws_line_real (x1, y1, x2, y2: REAL_64)
		-- As "draws_line" but with REAL_64 coordinates.
		do
			int_canvas_c_double_line (cnvs, x1, y1, x2, y2)
		end

	wd_draws_line (x1, y1, x2, y2: REAL_64)
		--	As "draws_line" but with World coordinates.
		do
			int_wd_canvas_line (cnvs, x1, y1, x2, y2)
		end

	draws_rect (xmin, xmax, ymin, ymax: INTEGER)
		-- Draws a rectangle with no filling. All points in the limits of 
		-- interval x_min<=x<=x_max, y_min<=y<=y_max will be painted. It is 
		-- affected by line attributes and the foreground color. If the active 
		-- driver does not include this primitive, it will be simulated using 
		-- the draws_line primitive.
		do
			int_canvas_rect (cnvs, xmin, xmax, ymin, ymax)
		end

	draws_rect_real (xmin, xmax, ymin, ymax: REAL_64)
		-- As "draws_rect" but with REAL_64 coordinates.
		do
			int_canvas_c_double_rect (cnvs, xmin, xmax, ymin, ymax)
		end

	wd_draws_rect (xmin, xmax, ymin, ymax: REAL_64)
		-- As "draws_rect" but with World coordinates.
		do
			int_wd_canvas_rect (cnvs, xmin, xmax, ymin, ymax)
		end

	draws_arc (xc, yc, w, h: INTEGER; angle1, angle2: REAL_64)
		-- Draws the arc of an ellipse aligned with the axis, using the current 
		-- foreground color and line width and style.
		--
		-- The coordinate (xc,yc) defines the center of the ellipse. Dimensions w 
		-- and h define the elliptic axes X and Y, respectively.
		--
		-- Angles angle1 and angle2 are in degrees and oriented counter-clockwise.
		-- They define the arc start and end, but they are not the angle relative 
		-- to the center, except when w=h and the ellipse is reduced to a circle. 
		-- The arc starts at the point
		-- (xc+(w/2)*cos(angle1), yc+(h/2)*sin(angle1)) and ends at
		-- (xc+(w/2)*cos(angle2), yc+(h/2)*sin(angle2)). 
		--	A complete ellipse can be drawn using 0 and 360 as the angles. If 
		-- angle2 is less than angle1 it will be increased by 360 until it is 
		-- greater than angle1.
		--
		-- The angles are specified so if the size of the ellipse (w x h) is 
		-- changed, its shape is preserved. So the angles relative to the center 
		-- are dependent from the ellipse size. The actual angle can be obtained 
		-- using rangle = atan2((h/2)*sin(angle), (w/2)*cos(angle)).
		do
			int_canvas_arc (cnvs, xc, yc, w, h, angle1, angle2)
		end

	draws_arc_real (xc, yc, w, h, angle1, angle2: REAL_64)
		-- As "draws_rect" but with REAL_64 coordinates.
		do
			int_canvas_c_double_arc (cnvs, xc, yc, w, h, angle1, angle2)
		end

	wd_draws_arc (xc, yc, w, h, angle1, angle2: REAL_64)
		-- As "draws_rect" but with World coordinates.
		do
			int_wd_canvas_arc (cnvs, xc, yc, w, h, angle1, angle2)
		end

	-- Attributes

	set_line_style (style: STRING)
		-- Configures the current line style for: CD_CONTINUOUS, CD_DASHED, 
		-- CD_DOTTED, CD_DASH_DOT, CD_DASH_DOT_DOT, or CD_CUSTOM.
		-- Default value: CD_CONTINUOUS. When CD_CUSTOM is used the 
		-- set_line_style_dahes feature must be called before to initialize the 
		-- custom dashes. The spaces are drawn with the background color, except 
		-- when back opacity is transparent then the background is left unchanged.
		require
			is_valid_line_style (style)
		local
			i: INTEGER
		do
			if style.is_equal("CD_CONTINUOUS") then
				i := int_canvas_line_style (cnvs, 0)
			elseif style.is_equal("CD_DASHED") then
				i := int_canvas_line_style (cnvs, 1)
			elseif style.is_equal("CD_DOTTED") then
				i := int_canvas_line_style (cnvs, 2)
			elseif style.is_equal("CD_DASH_DOT") then
				i := int_canvas_line_style (cnvs, 3)
			elseif style.is_equal("CD_DASH_DOT_DOT") then
				i := int_canvas_line_style (cnvs, 4)
			elseif style.is_equal("CD_CUSTOM") then
				i := int_canvas_line_style (cnvs, 5)
			end
		end

	get_line_style: STRING
		local
			i: INTEGER
		do
			i := int_canvas_line_style (cnvs, -1)
			
			if i.is_equal(0) then
				Result := "CD_CONTINUOUS"
			elseif i.is_equal(1) then
				Result := "CD_DASHED"
			elseif i.is_equal(2) then
				Result := "CD_DOTTED"
			elseif i.is_equal(3) then
				Result := "CD_DASH_DOT"
			elseif i.is_equal(4) then
				Result := "CD_DASH_DOT_DOT"
			elseif i.is_equal(5) then
				Result := "CD_CUSTOM"
			end
		end

	set_line_style_continuous
		local
			i: INTEGER
		do
			i := int_canvas_line_style (cnvs, 0)
		end

	set_line_style_dashed
		local
			i: INTEGER
		do
			i := int_canvas_line_style (cnvs, 1)
		end

	set_line_style_dotted
		local
			i: INTEGER
		do
			i := int_canvas_line_style (cnvs, 2)
		end

	set_line_style_dash_dot
		local
			i: INTEGER
		do
			i := int_canvas_line_style (cnvs, 3)
		end

	set_line_style_dash_dot_dot
		local
			i: INTEGER
		do
			i := int_canvas_line_style (cnvs, 4)
		end

	set_line_style_custom
		-- set_line_style_dahes feature must be called before to initialize the 
		-- custom dashes. 
		local
			i: INTEGER
		do
			i := int_canvas_line_style (cnvs, 5)
		end

	set_line_style_dashes (dashes: ARRAY[INTEGER])
		-- Defines the custom line style dashes. The first value is the length 
		-- of the first dash, the second value is the length of the first space, 
		-- and so on. For example: "10 2 5 2" means dash size 10, space size 2, 
		-- dash size 5, space size 2, and repeats the pattern. Sizes are
		-- in pixels.
		local
			marks: NATIVE_ARRAY[INTEGER]; i: INTEGER
		do
			marks := marks.calloc(dashes.count)

			from
            i := dashes.count - 1
         until
            i < 0
         loop
				marks.put(dashes.item(i), i)
            i := i - 1
         end

			int_canvas_line_style_dashes (cnvs, marks.to_external, dashes.count)
		end

	set_line_width (width: INTEGER)
		-- Configures the width of the current line (in pixels).
		-- Default value: 1. Valid width interval: >= 1.
		require
			width > 0
		local
			i: INTEGER
		do
			i := int_canvas_line_width (cnvs, width)
		end

	set_wd_line_width (width: REAL_64)
		-- Configures the current line width in millimeters. Valid width
		-- interval: >= 1.
		require
			width > 0
		local
			i: REAL_64
		do
			i := int_wd_canvas_line_width (cnvs, width)
		end

	get_line_width: INTEGER
		do
			Result := int_canvas_line_width (cnvs, -1)
		end

	get_wd_line_width: REAL_64
		do
			Result := int_wd_canvas_line_width (cnvs, -1)
		end

	set_line_join (style: STRING)
		-- Configures the current line style for: CD_MITER, CD_BEVEL or 
		-- CD_ROUND. Default value: CD_MITER. 
		require
			is_valid_line_join (style)
		local
			i: INTEGER
		do
			if style.is_equal("CD_MITER") then
				i := int_canvas_line_join (cnvs, 0)
			elseif style.is_equal("CD_BEVEL") then
				i := int_canvas_line_join (cnvs, 1)
			elseif style.is_equal("CD_ROUND") then
				i := int_canvas_line_join (cnvs, 2)
			end
		end

	get_line_join: STRING
		local
			i: INTEGER
		do
			i := int_canvas_line_join (cnvs, -1)

			if i.is_equal(0) then
				Result := "CD_MITER"
			elseif i.is_equal(1) then
				Result := "CD_BEVEL"
			elseif i.is_equal(2) then
				Result := "CD_ROUND"
			end
		end

	set_line_join_miter
		local
			i: INTEGER
		do
			i := int_canvas_line_join (cnvs, 0)
		end

	set_line_join_bevel
		local
			i: INTEGER
		do
			i := int_canvas_line_join (cnvs, 1)
		end

	set_line_join_round
		local
			i: INTEGER
		do
			i := int_canvas_line_join (cnvs, 2)
		end

	set_line_cap (style: STRING)
		-- Configures the current line style for: CD_CAPFLAT, CD_CAPSQUARE or 
		-- CD_CAPROUND. Default value: CD_CAPFLAT.
		require
			is_valid_line_cap (style)
		local
			i: INTEGER
		do
			if style.is_equal("CD_CAPFLAT") then
				i := int_canvas_line_cap (cnvs, 0)
			elseif style.is_equal("CD_CAPSQUARE") then
				i := int_canvas_line_cap (cnvs, 1)
			elseif style.is_equal("CD_CAPROUND") then
				i := int_canvas_line_cap (cnvs, 2)
			end
		end

	get_line_cap: STRING
		local
			i: INTEGER
		do
			i := int_canvas_line_cap (cnvs, -1)

			if i.is_equal(0) then
				Result := "CD_CAPFLAT"
			elseif i.is_equal(1) then
				Result := "CD_CAPSQUARE"
			elseif i.is_equal(2) then
				Result := "CD_CAPROUND"
			end
		end

	set_line_cap_flat
		local
			i: INTEGER
		do
			i := int_canvas_line_cap (cnvs, 0)
		end

	set_line_cap_square
		local
			i: INTEGER
		do
			i := int_canvas_line_cap (cnvs, 1)
		end

	set_line_cap_round
		local
			i: INTEGER
		do
			i := int_canvas_line_cap (cnvs, 2)
		end
			

feature {}

	-- Verifications

	is_valid_line_style (style: STRING): BOOLEAN
		do
			if style.is_equal("CD_CONTINUOUS") or
				style.is_equal("CD_DASHED") or
				style.is_equal("CD_DOTTED") or
				style.is_equal("CD_DASH_DOT") or
				style.is_equal("CD_DASH_DOT_DOT") or
				style.is_equal("CD_CUSTOM") then
				Result := True
			else
				Result := False
			end
		end

	is_valid_line_join (style: STRING): BOOLEAN
		do
			if style.is_equal("CD_MITER") or
				style.is_equal("CD_BEVEL") or
				style.is_equal("CD_ROUND") then
				Result := True
			else
				Result := False
			end
		end

	is_valid_line_cap (style: STRING): BOOLEAN
		do
			if style.is_equal("CD_CAPFLAT") or
				style.is_equal("CD_CAPSQUARE") or
				style.is_equal("CD_CAPROUND") then
				Result := True
			else
				Result := False
			end
		end

	-- Internals

	int_canvas_line (wgt: POINTER; x1, y1, x2, y2: INTEGER)
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "cdCanvasLine"
         }"
      end

	int_canvas_c_double_line (wgt: POINTER; x1, y1, x2, y2: REAL_64)
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "cdfCanvasLine"
         }"
      end

	int_wd_canvas_line (wgt: POINTER; x1, y1, x2, y2: REAL_64)
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "wdCanvasLine"
         }"
      end

	int_canvas_rect (wgt: POINTER; x1, x2, y1, y2: INTEGER)
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "cdCanvasRect"
         }"
      end

	int_canvas_c_double_rect (wgt: POINTER; x1, x2, y1, y2: REAL_64)
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "cdfCanvasRect"
         }"
      end

	int_wd_canvas_rect (wgt: POINTER; x1, x2, y1, y2: REAL_64)
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "wdCanvasRect"
         }"
      end

	int_canvas_arc (wgt: POINTER; xc, yc, w, h: INTEGER; a1, a2: REAL_64)
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "cdCanvasArc"
         }"
      end

	int_canvas_c_double_arc (wgt: POINTER; xc, yc, w, h, a1, a2: REAL_64)
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "cdfCanvasArc"
         }"
      end

	int_wd_canvas_arc (wgt: POINTER; xc, yc, w, h, a1, a2: REAL_64)
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "wdCanvasArc"
         }"
      end

	int_canvas_line_style (wgt: POINTER; s: INTEGER): INTEGER
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "cdCanvasLineStyle"
         }"
      end

	int_canvas_line_style_dashes (wgt, d: POINTER; c: INTEGER)
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "cdCanvasLineStyleDashes"
         }"
      end

	int_canvas_line_width (wgt: POINTER; w: INTEGER): INTEGER
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "cdCanvasLineWidth"
         }"
      end

	int_wd_canvas_line_width (wgt: POINTER; w: REAL_64): REAL_64
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "wdCanvasLineWidht"
         }"
      end

	int_canvas_line_join (wgt: POINTER; s: INTEGER): INTEGER
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "cdCanvasLineJoin"
         }"
      end

	int_canvas_line_cap (wgt: POINTER; s: INTEGER): INTEGER
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "cdCanvasLineCap"
         }"
      end

end

-- The MIT License (MIT)

-- Copyright (c) 2016 by German A. Arias

-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in 
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
